/***************************************************************
 * 链接freetds-devel库： /usr/lib64/libsybdb.so.5.1.0
 * $ gcc sample1.c -L/usr/lib64 -lsybdb -o sample1
 * Windows Server 防火墙需要创建mssql入站规则：打开默认的1433端口
 ***************************************************************/
#include <sybfront.h>  
#include <sybdb.h> 
#include <stdio.h>
#include <string.h>
#include <stdlib.h> 

typedef struct __mssql_conn
{
    char SQL_SERVER_IP[16];
    char SQL_SERVER_PORT[8];
    char SQL_SERVER[32];
    char user[32];
    char pass[64];
    char db[16];
    char table[32];

    DBINT result_code;  //定义保存数据库交易结果的类型
    DBPROCESS *dbprocess;   //数据库连接结果的句柄 
}MSSQL_CONN;

void mssql_conn_construct(MSSQL_CONN* conn, char* SQL_SERVER_IP, int SQL_SERVER_PORT,
                            char* user, char* pass,
                            char* db )
{
    //char s_port[25];
    //itoa(SQL_SERVER_PORT, s_port, 10);     //here 10 means decimal
    strcpy(conn->SQL_SERVER_IP, SQL_SERVER_IP);
   sprintf(conn->SQL_SERVER_PORT, "%d", SQL_SERVER_PORT);
   sprintf(conn->SQL_SERVER, "%s:%d", SQL_SERVER_IP, SQL_SERVER_PORT);
    strcpy(conn->user, user);
    strcpy(conn->pass, pass);
    strcpy(conn->db, db);
    //strcpy(conn->table, table);
}

int mssql_conn_open(MSSQL_CONN* conn)
{
    //建立到MSSQL数据库的连接------------------------   
    dbinit();                         //使用dbinit()函数, 进行freetds操作之前的初始化操作  
    LOGINREC *loginrec = dblogin();   //建立一个到数据库的连接的句柄  
    DBSETLUSER(loginrec, conn->user);  //向句柄中添加连接数据库的用户  
    DBSETLPWD(loginrec,  conn->pass);                     //向数据库连接句柄中添加密码  
    conn->dbprocess = dbopen(loginrec, conn->SQL_SERVER);   //连接数据库,并返回数据库连接结果的句柄  
          
    if(conn->dbprocess == FAIL)                                   //如果连接失败  
    {   
        fprintf(stderr, "Connect Fail\n");                  //在标准错误中输出信息  
        //exit(EXIT_FAILURE);                                 //进程异常退出  
        return 1;
    }  
    else                                                    //如果连接成功  
    {  
        printf("Connect success\n");  
    }  
           
    if(dbuse(conn->dbprocess, conn->db) == FAIL)                 //使用某个数据库，如果使用失败  
    {  
        dbclose(conn->dbprocess);                                 //关闭数据库连接句柄, 并且回收相关资源  
        //exit(EXIT_FAILURE);                                 //进程异常退出  
        return 2;
    }  
    return 0;
}


int main(int argc, char* argv[])
{
    MSSQL_CONN conn;
    mssql_conn_construct(&conn, "172.24.1.122", 1433,
                            "sa", "passw0rd",
                            "testDB");
    //建立到MSSQL数据库的连接------------------------   
    mssql_conn_open(&conn);
    //开始进行数据库中数据查询的工作------------------  
    char mssqlbuf[1024];                                    //定义保存数据库查询语句的字符串  
    memset(mssqlbuf, 0x00, sizeof(mssqlbuf));               //开始初始化字符串  
    char sql[1024]; memset(sql, 0, 1024);
    sprintf(mssqlbuf, "SELECT name, age FROM testTable");   //组装操作sql的语句, 将sql语句保存到mssqlbuf  
    dbcmd(conn.dbprocess, mssqlbuf);                             //将刚刚组装好的sql命令, 使用dbcmd命令保存到数据库连接句柄的缓存中  
                              
    if(dbsqlexec(conn.dbprocess) == FAIL)                        //如果执行的命令失败  
    {   
        dbclose(conn.dbprocess);                                 //关闭数据库操作进程  
        exit(EXIT_FAILURE);                                 //程序异常退出  
    }  
      
    char name[100];                                         //定义两个变量来保存绑定出来的数据  
    char age[10];  
    memset(name, 0x00, sizeof(name));                       //对数组进行初始化  
    memset(age, 0x00, sizeof(age));  
      
    //开始对数据取出的进行操作-------------------------  
    if((conn.result_code = dbresults(conn.dbprocess)) != NO_MORE_RESULTS && conn.result_code == SUCCEED)  //如果sql命令执行成功  
    {  
        int nCols = dbnumcols(conn.dbprocess);
         //开始绑定数据  
        dbbind(conn.dbprocess, 1, CHARBIND, (DBCHAR)0, (BYTE*)name);    //将数据库中查找到的name(sql命令中我们查找的时候name位于结果的第一个), 绑定给本地的name  
        dbbind(conn.dbprocess, 2, CHARBIND, (DBCHAR)0, (BYTE*)age);     //将数据库中查找到的age(sql命令中我们查找的时候age位于结果的第二个), 绑定给本地的age  
          
        while(dbnextrow(conn.dbprocess) != NO_MORE_ROWS)                //开始遍历结果集合, 并且没执行一次判断一次是否还有后续数据  
        {  
            //这里添加你想要的对取出数据的操作  
            printf("name: %s, age: %s\n", name, age);            //使用printf输出我们取出的name(本机变量), age(本机变量)  
            memset(name, 0, sizeof(name)); memset(age, 0, sizeof(argc));
        }   

        int nRows = dbcount(conn.dbprocess);                    //统计及结果集被处理的行数
        printf("nCols=%d\tnRows=%d\n", nCols, nRows);          
    }  
          
    dbclose(conn.dbprocess);                                            //关闭数据库连接   

    return 0;
}